package com.example.analyzevisio.utis;

import com.example.analyzevisio.model.component.Items;
import com.example.analyzevisio.model.component.Position;
import com.example.analyzevisio.service.*;
import com.sun.org.apache.xerces.internal.impl.xpath.XPath;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/*
获取各组件元素方法
 */
public class Obtain {

    //整体类型的map
    private static HashMap<String, Map<String, String>> dataMap;
    //节点类型的map
    private static HashMap<String, String> typeMap;

    public static HashMap<String, Map<String, String>> getDataMap(){
        return dataMap;
    }



    /**
     * 获取节点的坐标和父节点
     *
     * @param shapeElement
     * @return
     */
    public static Map<String, String> getObtainCoordinates(Element shapeElement) {
        HashMap<String, String> hashMap = new HashMap<>();

        LaneService laneService = new LaneService();
        Map<String, List<Position>> positionMap = laneService.getPosition();

        List<String> matches = getStrings(shapeElement);
        for (String match : matches) {
            if (dataMap.containsKey(match)) {
                Map<String, String> stringMap = dataMap.get(match);

                List<Position> positions = positionMap.get(match);

                double primarypinX = Math.ceil(Double.parseDouble(getCellValue(shapeElement, "PinX")) * 25.4);
                double primaryPinY = Math.ceil(Double.parseDouble(getCellValue(shapeElement, "PinY")) * 25.4);

                double pinX = (primarypinX - positions.get(1).getX()) * 2 + positions.get(0).getX();

                //高度差
                double differ = (positions.get(1).getY() - primaryPinY) * 2;
                double pinY = positions.get(1).getY() + differ - positions.get(0).getY();

                hashMap.put("parent", stringMap.get("UniqueID"));
                hashMap.put("pinX", String.valueOf(pinX));
                hashMap.put("pinY", String.valueOf(pinY));
            }
        }
        return hashMap;
    }

    /**
     * 文本获取
     *
     * @param textNodes
     * @return
     */
    public static String getText(NodeList textNodes) {
        String s = textNodes.getLength() > 0 ? textNodes.item(0).getTextContent() : null;
        if (s != null) {
            String substring = s.trim();
            return substring;
        }
        return s;
    }

    /**
     * 获取连接点坐标
     *
     * @param
     * @return
     */
    public static List<Items> getConnectionPoint(String name) {

        ArrayList<Items> items = new ArrayList<>();
        //左
        Items left = new Items();
        left.setId("port1");
        left.setGroup("group1");
        HashMap<String, String> leftArgs = new HashMap<>();

        //右
        Items rigth = new Items();
        rigth.setId("port2");
        rigth.setGroup("group1");
        HashMap<String, String> rigthArgs = new HashMap<>();

        //上
        Items upper = new Items();
        upper.setId("port3");
        upper.setGroup("group1");
        HashMap<String, String> upperArgs = new HashMap<>();

        //下
        Items below = new Items();
        below.setId("port4");
        below.setGroup("group1");
        HashMap<String, String> belowArgs = new HashMap<>();

        if ("服务".equals(name)) {
            leftArgs.put("x", "10");
            leftArgs.put("y", "12.5");

            rigthArgs.put("x", "70");
            rigthArgs.put("y", "12.5");

            upperArgs.put("x", "40");
            upperArgs.put("y", "4");

            belowArgs.put("x", "40");
            belowArgs.put("y", "22");

        } else if ("起始".equals(name)) {
            leftArgs.put("x", "8");
            leftArgs.put("y", "20");

            rigthArgs.put("x", "32");
            rigthArgs.put("y", "20");

            upperArgs.put("x", "20");
            upperArgs.put("y", "8");

            belowArgs.put("x", "20");
            belowArgs.put("y", "32");

        }
        left.setArgs(leftArgs);

        rigth.setArgs(rigthArgs);

        upper.setArgs(upperArgs);

        below.setArgs(belowArgs);

        items.add(left);
        items.add(rigth);
        items.add(upper);
        items.add(below);
        return items;
    }


    /*
    连接线连接点
     */
    public static String getToPart(double pinX, double pinY, double x, double y) {


        if (pinX == x) {
            if (pinY > y) {
                return "port4";
            } else {
                return "port3";
            }
        }

        if (pinY == y) {
            if (pinX > x) {
                return "port1";
            } else {
                return "port2";
            }
        }

        return null;
    }


    /**
     * 获取关系组件
     *
     * @param shapeElement
     * @return
     */
    public static List<String> getStrings(Element shapeElement) {
        String relationships = getCellValue(shapeElement, "Relationships");
        String regex = "(?<=\\.)[^!]*(?=!)";
        // 创建 Pattern 对象
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(relationships);
        // 用于存储匹配结果的列表
        List<String> matches = new ArrayList<>();
        while (matcher.find()) {
            matches.add(matcher.group().trim()); // trim() 去除首尾空白字符
        }
        return matches;
    }

    /**
     * 获取Cell属性值
     *
     * @param shapeElement
     * @param cellName
     * @return
     */
    public static String getCellValue(Element shapeElement, String cellName) {
        NodeList cellNodes = shapeElement.getElementsByTagName("Cell");
        for (int j = 0; j < cellNodes.getLength(); j++) {
            Node cellNode = cellNodes.item(j);
            if (cellNode.getNodeType() == Node.ELEMENT_NODE) {
                Element cellElement = (Element) cellNode;
                if (cellElement.getAttribute("N").equals(cellName) && "Relationships".equals(cellName)) {
                    return cellElement.getAttribute("F");
                } else if (cellElement.getAttribute("N").equals(cellName)) {
                    return cellElement.getAttribute("V");
                }
            }
        }
        return null;
    }

    /*
    整体data输入
     */
    public static void extracted(String pageFilePath, NodeList shapeNodes) throws Exception {
        String nodeMaster = "0", seviceMaster = "0",
                judgeMaster = "0", laneMaster = "0", connectMaster = "0",
                horizontalLaneMaster = "0";
        typeMap = new HashMap<>();


//        String pageFilePath = "C:\\Users\\ms206\\Desktop\\visio图\\代码解压\\visio\\masters\\masters.xml";

        File xmlFile = new File(pageFilePath);
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(xmlFile);
        doc.getDocumentElement().normalize();

        NodeList masterNodes = doc.getElementsByTagName("Master");
        for (int i = 0; i < masterNodes.getLength(); i++) {
            Element shapeElement = (Element) masterNodes.item(i);

            String shapeMaster = shapeElement.getAttribute("ID");
            String nameU = shapeElement.getAttribute("NameU");
            switch (nameU) {
                case "Start/End":
                    nodeMaster = shapeMaster;
                    typeMap.put("开始/结束", shapeMaster);
                    break;

                case "Process":
                    seviceMaster = shapeMaster;
                    typeMap.put("流程", shapeMaster);
                    break;

                case "Decision":
                    judgeMaster = shapeMaster;
                    typeMap.put("判定", shapeMaster);
                    break;


                case "Swimlane":
                    horizontalLaneMaster = shapeMaster;
                    typeMap.put("水平泳道", shapeMaster);
                    break;

                case "Swimlane (vertical)":
                    laneMaster = shapeMaster;
                    typeMap.put("泳道", shapeMaster);
                    break;

                case "Dynamic connector":
                    connectMaster = shapeMaster;
                    typeMap.put("动态连接线", shapeMaster);
                    break;
            }

        }


        VSDXParser vsdxParser = new VSDXParser();
        vsdxParser.setTypeMap(typeMap);


        dataMap = new HashMap<>();
        int lane = -1, start = -1, serviceTask = -1, choice = -1, succeed = -1,
                fail = -1;
        for (int i = 0; i < shapeNodes.getLength(); i++) {
            Element shapeElement = (Element) shapeNodes.item(i);
            String shapeMaster = shapeElement.getAttribute("Master");
            HashMap<String, String> hashMap = new HashMap<>();
            if (horizontalLaneMaster.equals(shapeMaster)) {
                throw new RuntimeException("暂不支持水平泳道");
            }
            if (connectMaster.equals(shapeMaster) ||
                    laneMaster.equals(shapeMaster) ||
                    seviceMaster.equals(shapeMaster) ||
                    nodeMaster.equals(shapeMaster) ||
                    judgeMaster.equals(shapeMaster)
            ) {
                if (connectMaster.equals(shapeMaster)) {
                    choice++;
                    hashMap.put("stateId", "Choice" + choice);
                    hashMap.put("type", "连接线");
                } else if (laneMaster.equals(shapeMaster)) {
                    lane++;
                    hashMap.put("stateId", "lane" + lane);
                    hashMap.put("type", "泳道");
                } else if (seviceMaster.equals(shapeMaster)) {
                    serviceTask++;
                    hashMap.put("stateId", "ServiceTask" + serviceTask);
                    hashMap.put("type", "流程");
                } else if (nodeMaster.equals(shapeMaster)) {
                    NodeList textNodes = shapeElement.getElementsByTagName("Text");
                    String s = getText(textNodes);
                    if ("开始".equals(s)) {
                        start++;
                        hashMap.put("stateId", "Start" + start);
                        hashMap.put("type", "开始");
                    } else if ("成功".equals(s)) {
                        succeed++;
                        hashMap.put("stateId", "Succeed" + succeed);
                        hashMap.put("type", "成功");
                    } else if ("失败".equals(s)) {
                        fail++;
                        hashMap.put("stateId", "Fail" + fail);
                        hashMap.put("type", "失败");
                    }
                }else if (judgeMaster.equals(shapeMaster)){
                    hashMap.put("type", "判断");
                }

                String shapeID = shapeElement.getAttribute("ID");
                String uniqueID = shapeElement.getAttribute("UniqueID");

                String substring = uniqueID.substring(1, uniqueID.length() - 1);
                double pinX = Math.ceil(Double.parseDouble(getCellValue(shapeElement, "PinX")) * 25.4);
//                System.out.println(shapeID);
                double PinY = Math.ceil(Double.parseDouble(getCellValue(shapeElement, "PinY")) * 25.4);

                hashMap.put("Master", shapeMaster);
                hashMap.put("UniqueID", substring);
                hashMap.put("pinX", pinX + "");
                hashMap.put("PinY", PinY + "");

                hashMap.put("sum", "0");
                hashMap.put("enterJudgment", "false");

                dataMap.put(shapeID, hashMap);


                NodeService nodeService = new NodeService();
                JudgeService judgeService = new JudgeService();
                ServiceNodeService serviceNodeService = new ServiceNodeService();
                ConnectService connectService = new ConnectService();
                LaneService laneService = new LaneService();
                laneService.setDataMap(dataMap);
                judgeService.setDataMap(dataMap);
                nodeService.setDataMap(dataMap);
                serviceNodeService.setDataMap(dataMap);
                connectService.setDataMap(dataMap);
            }
        }
    }



    /**
     * 递归删除目录下的所有文件和子目录。
     *
     * @param dir 要清空的目录路径
     * @throws IOException 如果删除过程中发生错误
     */
    public static void deleteDirectoryContents(Path dir) throws IOException {
        if (Files.exists(dir) && Files.isDirectory(dir)) {
            Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
        } else {
            System.out.println("指定路径不是一个存在的目录: " + dir);
        }
    }


    /**
     * 判断起始节点是否正确
     *
     * @param start
     * @param fail
     * @param success
     */
    public static void nodeJudgment(int start, int fail, int success) {
        StringBuilder stringBuilder = new StringBuilder();

        if (start < 1) {
            stringBuilder.append("没有起始节点，注意查看;\n");
        } else if (start > 1){
            stringBuilder.append("含有多个起始节点，注意查看;\n");
        }

        if (fail < 1) {
            stringBuilder.append("不存在失败节点，注意查看;\n");
        }

        if (success < 1) {
            stringBuilder.append("不存在失败节点，注意查看;\n");
        }

        if (stringBuilder.length() > 0){

            throw new RuntimeException("不造啊！" + stringBuilder);
        }
    }

    /**
     * 判断连接点的节点是否正常
     * @param
     * @param point
     */
    public static void ConnectionPointJudgment(String toSheetId , boolean point){
        String str = null;

        Map<String, String> stringMap = dataMap.get(toSheetId);
        String type = stringMap.get("type");

        if (point){
            //出点
            if ("失败".equals(type) || "成功".equals(type)){
                str = "失败或成功节点不能连出";
            }
            int sum = Integer.parseInt(stringMap.get("sum"));
            if ("开始".equals(type) && sum > 0){
                str = "失败或成功节点不能连出";
            }

            stringMap.put("sum", String.valueOf(Integer.parseInt(stringMap.get("sum"))+1));



        }else {
            //入点
            if ("开始".equals(type)){
                str = "不能连入开始节点";
            }

            stringMap.put("enterJudgment","true");
            stringMap.put("sum", String.valueOf(Integer.parseInt(stringMap.get("sum"))+1));

        }

        dataMap.put(toSheetId,stringMap);

        if (! (str == null)){
            throw new RuntimeException( str );
        }
    }
}
